#!/bin/bash

firehol_check_init() {
  :
}

firehol_check_file() {
  local filename="$1" status=0

  case $filename in
    sbin/Makefile.in)
      :
    ;;
    configure.ac|sbin/install.config.in.in)
      check_commands sbin/firehol || status=1
      check_commands sbin/fireqos || status=1
      check_commands sbin/link-balancer || status=1
      check_commands sbin/update-ipsets || status=1
      check_commands sbin/vnetbuild || status=1
      check_detection_useful sbin/firehol sbin/fireqos sbin/link-balancer sbin/update-ipsets  sbin/vnetbuild || status=1
    ;;
    sbin/firehol|sbin/fireqos|sbin/link-balancer|sbin/update-ipsets|sbin/vnetbuild)
      check_commands $filename || status=1
    ;;
    doc/services-db.data)
      doc/tools/mkservicelinks /dev/null doc/services-db.data sbin/firehol sbin/services.common sbin/services.firehol || status=1
    ;;
    *)
      #echo "No checks found for $filename"
      :
    ;;
  esac
  return $status
}

firehol_check_fin() {
  :
}

check_commands() {
  local status=0

  touch $MYTMP/commands-checked
  if grep -q -F -z "$1" $MYTMP/commands-checked
  then
    # Only check a file once - an edit to some files checks multiple
    return 0
  else
    echo "$1" >> $MYTMP/commands-checked
  fi

  get_staged_file $1
  get_staged_file configure.ac
  get_staged_file sbin/install.config.in.in
  get_staged_file sbin/functions.common

  # Find commands that have been enclosed in quotes and remove anything after
  #  if nothing matched the substitution, proceed to the next line
  #  if the command is used in a -z check, proceed to the next line
  #  if the command is in posix size check [ "$var" ], proceed to the next line
  #  if the command is being assigned to a variable, proceed to the next line
  #  if the command is being used in an eval, proceed to the next line
  # Anything left, print the line number
  sed -n -e 's/.*\([(`|&][^)`]*"\$[^("}]*_CMD}*\).*/\1/' \
         -e 's/^[ 	]*\("\$[^("}]*_CMD}*\)/\1/' \
         -e T \
         -e '/-z *"\$/b' \
         -e '/\[ *"\$/b' \
         -e '/= *"\$/b' \
         -e '/eval *"\$/b' \
         -e '{=}' \
         $MYTMP/files/$1 > $MYTMP/errors
  if [ -s $MYTMP/errors ]
  then
    status=1
    echo "Detected use(s) of \"\${SOMETHING_CMD}\" in ${1}. Check lines:"
    cat $MYTMP/errors
  fi

  # Ignore lines from the command table and require_cmd entries
  # ensure at least 2 characters before and after each word, reset cond jump
  # extract the command and immediate surroundings, got to next line if no match
  # remove brackets
  # proceed to next line if command starts with a dollar
  # proceed to next line if command ends with equals (assignment)
  # print line number
  sed -n -e '/^	*[YN]|/b' -e '/require_cmd/b' \
         -e 's/^/  /' -e 's/$/  /' -e T \
         -e 's/.*\(..\<[A-Z0-9_]*_CMD..\).*/\1/' -e T \
         -e 's/[{}]//' \
         -e '/$[A-Z]/b' \
         -e '/[A-Z0-9]=/b' \
         -e '=' \
         $MYTMP/files/$1 > $MYTMP/errors
  if [ -s $MYTMP/errors ]
  then
    status=1
    echo "Detected use(s) of 'SOMETHING_CMD' (missing \$) in ${1}. Check lines:"
    cat $MYTMP/errors
  fi

  sed -n -e 's/\(.*_CMD\)="[@]\(.*\)[@]"/\1 \2/p' $MYTMP/files/sbin/install.config.in.in > $MYTMP/commands-defined

  for cmd in $(tr " " "\n" < $MYTMP/files/$1 |
             sed -n -e 's/.*\(\<[A-Z0-9_]*_CMD\).*/\1/p' | sort | uniq)
  do
    autocmd=`grep "^${cmd} " $MYTMP/commands-defined | cut -f2 -d' '`
    if [ ! "$autocmd" ]
    then
      status=1
      echo "sbin/install.config.in.in: missing definition of $cmd (for $1)"
    fi

    if ! grep -q "_${autocmd}(\|\[$autocmd\]" $MYTMP/files/configure.ac
    then
      status=1
      echo "configure.ac: missing detection of $autocmd (for $1)"
    fi
  done

  (
   a=`pwd`
   cd $MYTMP/files
   $a/packaging/firehol/detect-cmd.pl configure.ac $1 || touch $MYTMP/detect
  )
  if [ -f $MYTMP/detect ]; then status=1; fi

  return $status
}

check_detection_useful() {
  local status=0

  touch $MYTMP/commands-checked
  if grep -q -F -z "$1" $MYTMP/commands-checked
  then
    # Only check a file once - an edit to some files checks multiple
    return 0
  else
    echo "$1" >> $MYTMP/commands-checked
  fi

  list=
  for i in "$@"
  do
    get_staged_file $1
    list="$list $MYTMP/files/$1"
  done
  get_staged_file configure.ac
  get_staged_file sbin/install.config.in.in
  get_staged_file sbin/functions.common

  sed -n -e 's/\(.*_CMD\)="[@]\(.*\)[@]"/\1 \2/p' $MYTMP/files/sbin/install.config.in.in > $MYTMP/commands-defined

  while read cmd subst
  do
    if ! grep -q "\${*$cmd" $list $MYTMP/files/sbin/functions.*
    then
      status=1
      echo "$cmd detected but never used in $1 or function libraries"
    fi
  done < $MYTMP/commands-defined
}
